package com.novunda.platform.entities;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.google.common.collect.Lists;
import com.novunda.platform.entities.base.DataEntity;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import org.hibernate.annotations.Where;
import org.hibernate.validator.constraints.Length;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.List;

/**
 * 角色Entity
 * 
 * @author slacrey
 * @version 2013-05-15
 */
@Entity
@Table(name = "sys_role")
@DynamicInsert
@DynamicUpdate
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Role extends DataEntity {

  private static final long serialVersionUID = 1L;
  private Long id; // 编号
  private Office office; // 归属机构
  private String name; // 角色名称
  private String enname; // 英文名称
  private String roleType;// 权限类型
  private String dataScope; // 数据范围

  private List<User> userList = Lists.newArrayList(); // 拥有用户列表
  private List<Menu> menuList = Lists.newArrayList(); // 拥有菜单列表
  private List<Office> officeList = Lists.newArrayList(); // 按明细设置数据范围
  
  private boolean checked;//是否选中


  // 数据范围（1：所有数据；2：所在公司及以下数据；3：所在公司数据；4：所在部门及以下数据；5：所在部门数据；8：仅本人数据；9：按明细设置）
  public static final String DATA_SCOPE_ALL = "1";
  /**
   * 所在公司及以下数据
   */
  public static final String DATA_SCOPE_COMPANY_AND_CHILD = "2";
  /**
   * 所在公司数据
   */
  public static final String DATA_SCOPE_COMPANY = "3";
  /**
   * 所在部门及以下数据
   */
  public static final String DATA_SCOPE_OFFICE_AND_CHILD = "4";
  /**
   * 所在部门数据
   */
  public static final String DATA_SCOPE_OFFICE = "5";
  /**
   * 仅本人数据
   */
  public static final String DATA_SCOPE_SELF = "8";
  /**
   * 按明细设置
   */
  public static final String DATA_SCOPE_CUSTOM = "9";

  public Role() {
    dataScope = DATA_SCOPE_CUSTOM;
  }

  public Role(Long id, String name) {
    this();
    this.id = id;
    this.name = name;
  }

  public Role(Long id, String name, String enname) {
    this.id = id;
    this.name = name;
    this.enname = enname;
  }

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  @ManyToOne
  @JoinColumn(name = "office_id")
  @NotFound(action = NotFoundAction.IGNORE)
  public Office getOffice() {
    return office;
  }

  public void setOffice(Office office) {
    this.office = office;
  }

  @Length(min = 1, max = 100)
  @Column(name = "name")
  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  @Length(min = 1, max = 100)
  @Column(name = "enname")
  public String getEnname() {
    return enname;
  }

  public void setEnname(String enname) {
    this.enname = enname;
  }

  @Length(min = 1, max = 100)
  @Column(name = "role_type")
  public String getRoleType() {
    return roleType;
  }

  public void setRoleType(String roleType) {
    this.roleType = roleType;
  }

  @Column(name = "data_scope")
  public String getDataScope() {
    return dataScope;
  }

  public void setDataScope(String dataScope) {
    this.dataScope = dataScope;
  }

  @ManyToMany(mappedBy = "roleList", fetch = FetchType.LAZY)
  @Where(clause = "del_flag='" + DEL_FLAG_NORMAL + "'")
  @OrderBy("id")
  @Fetch(FetchMode.SUBSELECT)
  @NotFound(action = NotFoundAction.IGNORE)
  @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
  public List<User> getUserList() {
    return userList;
  }

  public void setUserList(List<User> userList) {
    this.userList = userList;
  }

  @Transient
  public List<Long> getUserIdList() {
    List<Long> nameIdList = Lists.newArrayList();
    for (User user : userList) {
      nameIdList.add(user.getId());
    }
    return nameIdList;
  }

  @Transient
  public String getUserIds() {
    List<Long> nameIdList = Lists.newArrayList();
    for (User user : userList) {
      nameIdList.add(user.getId());
    }
    return StringUtils.join(nameIdList, ",");
  }

  @ManyToMany(fetch = FetchType.LAZY)
  @JoinTable(name = "sys_role_menu", joinColumns = @JoinColumn(name = "role_id") , inverseJoinColumns = @JoinColumn(name = "menu_id") )
  @Where(clause = "del_flag='" + DEL_FLAG_NORMAL + "'")
  @OrderBy("id")
  @Fetch(FetchMode.SUBSELECT)
  @NotFound(action = NotFoundAction.IGNORE)
  @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
  public List<Menu> getMenuList() {
    return menuList;
  }

  public void setMenuList(List<Menu> menuList) {
    this.menuList = menuList;
  }

  @Transient
  public List<Long> getMenuIdList() {
    List<Long> menuIdList = Lists.newArrayList();
    for (Menu menu : menuList) {
      menuIdList.add(menu.getId());
    }
    return menuIdList;
  }

  @Transient
  public void setMenuIdList(List<Long> menuIdList) {
    menuList = Lists.newArrayList();
    for (Long menuId : menuIdList) {
      Menu menu = new Menu();
      menu.setId(menuId);
      menuList.add(menu);
    }
  }

  @Transient
  public String getMenuIds() {
    List<Long> nameIdList = Lists.newArrayList();
    for (Menu menu : menuList) {
      nameIdList.add(menu.getId());
    }
    return StringUtils.join(nameIdList, ",");
  }

  @Transient
  public void setMenuIds(String menuIds) {
    menuList = Lists.newArrayList();
    if (menuIds != null) {
      String[] ids = StringUtils.split(menuIds, ",");
      for (String menuId : ids) {
        Menu menu = new Menu();
        menu.setId(Long.valueOf(menuId));
        menuList.add(menu);
      }
    }
  }

  @ManyToMany(fetch = FetchType.EAGER)
  @JoinTable(name = "sys_role_office", joinColumns = @JoinColumn(name = "role_id") , inverseJoinColumns = @JoinColumn(name = "office_id") )
  @Where(clause = "del_flag='" + DEL_FLAG_NORMAL + "'")
  @OrderBy("id")
  @Fetch(FetchMode.SUBSELECT)
  @NotFound(action = NotFoundAction.IGNORE)
  @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
  public List<Office> getOfficeList() {
    return officeList;
  }

  public void setOfficeList(List<Office> officeList) {
    this.officeList = officeList;
  }

  @Transient
  public List<Long> getOfficeIdList() {
    List<Long> officeIdList = Lists.newArrayList();
    for (Office office : officeList) {
      officeIdList.add(office.getId());
    }
    return officeIdList;
  }

  @Transient
  public void setOfficeIdList(List<Long> officeIdList) {
    officeList = Lists.newArrayList();
    for (Long officeId : officeIdList) {
      Office office = new Office();
      office.setId(officeId);
      officeList.add(office);
    }
  }

  @Transient
  public String getOfficeIds() {
    List<Long> nameIdList = Lists.newArrayList();
    for (Office office : officeList) {
      nameIdList.add(office.getId());
    }
    return StringUtils.join(nameIdList, ",");
  }

  @Transient
  public void setOfficeIds(String officeIds) {
    officeList = Lists.newArrayList();
    if (officeIds != null) {
      String[] ids = StringUtils.split(officeIds, ",");
      for (String officeId : ids) {
        Office office = new Office();
        office.setId(Long.valueOf(officeId));
        officeList.add(office);
      }
    }
  }

  // @ElementCollection
  // @CollectionTable(name = "sys_user_role", joinColumns = { @JoinColumn(name =
  // "role_id") })
  // @Column(name = "user_id")
  // @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
  // public List<Long> getUserIdList() {
  // return userIdList;
  // }
  //
  // public void setUserIdList(List<Long> userIdList) {
  // this.userIdList = userIdList;
  // }

  /**
   * 获取权限字符串列表
   */
  @Transient
  public List<String> getPermissions() {
    List<String> permissions = Lists.newArrayList();
    for (Menu menu : menuList) {
      if (menu.getPermission() != null && !"".equals(menu.getPermission())) {
        permissions.add(menu.getPermission());
      }
    }
    return permissions;
  }

  @Transient
  public boolean isAdmin() {
    return isAdmin(id);
  }

  @Transient
  public static boolean isAdmin(Long id) {
    return Long.valueOf(1L).equals(id);
  }

  @Transient
  public boolean isChecked() {
    return checked;
  }

  @Transient
  public void setChecked(boolean checked) {
    this.checked = checked;
  }

  // @Transient
  // public String getMenuNames() {
  // List<String> menuNameList = Lists.newArrayList();
  // for (Menu menu : menuList) {
  // menuNameList.add(menu.getName());
  // }
  // return StringUtils.join(menuNameList, ",");
  // }
}
